package net.openvision.music.model;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

public class DefaultScoreModel implements ScoreModel {
	private List<ScoreDataListener> listeners;
	//private List<Staff> staves;
	private DocumentInformation documentInfo;
	private ScoreEnvironment environment;
	private List<Bar[]> bars;
	private List<StaffInformation> staves;
	
	public DefaultScoreModel() {
		listeners = new LinkedList<ScoreDataListener>();
		//staves = new ArrayList<Staff>();

		documentInfo = new DocumentInformation(this);
		environment = new ScoreEnvironment();
		bars = new ArrayList<Bar[]>();
		staves = new ArrayList<StaffInformation>();
	}

	protected void fireDocumentInformationChanged(String name, String newValue) {
		for (ScoreDataListener l : listeners) {
			l.documentInformationChanged(name, newValue);
		}
	}

	protected void fireScoreDataChanged(ScoreDataEvent event) {
		for (ScoreDataListener l : listeners) {
			l.scoreDataChanged(event);
		}
	}

	@Override
	public void addListener(ScoreDataListener listener) {
		listeners.add(listener);
	}
	
	public void addBar() {
		Bar[] newBar = new Bar[staves.size()];
		for (int i = 0; i < newBar.length; i++) {
			newBar[i] = new Bar(i, bars.size());
		}
		bars.add(newBar);
	}
	
	public void addStaff(StaffInformation staff) {
		staves.add(staff);
		for (int i = 0; i < bars.size(); i++) {
			Bar[] b = new Bar[bars.get(i).length + 1];
			System.arraycopy(bars.get(i), 0, b, 0, bars.get(i).length);
			b[b.length-1] = new Bar(b.length-1, i);
			bars.set(i, b);
		}
	}

	@Override
	public Bar[] getBarsAt(int index) {
		return bars.get(index);
	}

	@Override
	public DocumentInformation getDocumentInformation() {
		return documentInfo;
	}

	@Override
	public <T> T getEnvironmentVariable(Class<T> clazz, int staff, int bar,
			Length position) {
		return environment.getValueAt(staff, bar, position, clazz);
	}

	@Override
	public StaffInformation getStaffInformation(int index) {
		return staves.get(index);
	}

	@Override
	public void removeListener(ScoreDataListener listener) {
		listeners.remove(listener);
	}

	@Override
	public int getBarCount() {
		return bars.size();
	}

	@Override
	public int getStaffCount() {
		return staves.size();
	}

//	public int getBarCount() {
//		return (staves.size() > 0) ? staves.get(0).getBarCount() : 0;
//	}
//	
//	public int getStaffCount() {
//		return staves.size();
//	}
//
//	public Staff getStaffAt(int i) {
//		return staves.get(i);
//	}
//
//	public Iterable<Staff> getStaves() {
//		return staves;
//	}
//	
//	public Staff addStaff() {
//		Staff result = new Staff(this, getBarCount());
//		staves.add(result);
//		return result;
//	}
//	
//	public TimeSignature getTimeSignature(int bar) {
//		return null; /* TODO */
//	}
//
//	public DocumentInformation getDocumentInformation() {
//		return documentInfo;
//	}
//	
//	ScoreEnvironment getScoreEnvironment() {
//		return environment;
//	}
}
